package com.devenv.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 用户实体类
 * <p>
 * 开源版本的用户实体，移除了商业功能相关字段：
 * - 微信登录相关字段 (wechatOpenid, wechatUnionid)
 * - 头像审核相关字段 (avatarStatus, avatarUploadedAt, avatarApprovedAt, avatarRejectedAt, avatarRejectionReason)
 * </p>
 * 
 * @author DevEnv OpenSource Team
 * @version 1.0.0
 * @since 1.0.0
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "`user`", indexes = {
    @Index(name = "idx_user_username", columnList = "username"),
    @Index(name = "idx_user_email", columnList = "email"),
    @Index(name = "idx_user_status", columnList = "status")
})
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", unique = true, length = 50, nullable = false)
    private String username;

    @Column(name = "email", unique = true, length = 100)
    private String email;

    @Column(name = "password", length = 255)
    private String password;

    @Column(name = "nickname", length = 50)
    private String nickname;

    @Column(name = "avatar_url", length = 500)
    private String avatarUrl;

    @Column(name = "phone", length = 20)
    private String phone;

    @Column(name = "bio", length = 500)
    private String bio;

    @Column(name = "login_type", length = 20, nullable = false)
    private String loginType = "normal"; // normal, oauth

    @Column(name = "status", nullable = false)
    private Integer status = 1; // 1:正常 0:禁用

    @Enumerated(EnumType.STRING)
    @Column(name = "role", length = 20, nullable = false)
    private UserRole role = UserRole.USER;

    @Column(name = "login_count", nullable = false)
    private Long loginCount = 0L;

    @Column(name = "last_login_time")
    private LocalDateTime lastLoginTime;

    @Column(name = "last_login_ip", length = 50)
    private String lastLoginIp;

    // 统计相关字段
    @Column(name = "script_generation_count", nullable = false)
    private Integer scriptGenerationCount = 0;

    @Column(name = "template_creation_count", nullable = false)
    private Integer templateCreationCount = 0;

    @Column(name = "last_active_time")
    private LocalDateTime lastActiveTime;

    @Column(name = "profile_completion", precision = 3, scale = 2)
    private BigDecimal profileCompletion = BigDecimal.ZERO;

    // 用户偏好设置（JSON格式）
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "preferences")
    private Map<String, Object> preferences;

    // 验证状态
    @Column(name = "email_verified", nullable = false)
    private Boolean emailVerified = false;

    @Column(name = "phone_verified", nullable = false)
    private Boolean phoneVerified = false;

    @Column(name = "email_verification_code", length = 10)
    private String emailVerificationCode;

    // 密码重置相关
    @Column(name = "password_reset_token", length = 64)
    private String passwordResetToken;

    @Column(name = "password_reset_token_expiry")
    private LocalDateTime passwordResetTokenExpiry;

    @CreationTimestamp
    @Column(name = "created_at")
    private LocalDateTime createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    /**
     * 计算资料完整度
     */
    public void calculateProfileCompletion() {
        double completion = 0.0;

        // 基础信息 (40%)
        if (username != null && !username.trim().isEmpty()) completion += 0.1;
        if (email != null && !email.trim().isEmpty()) completion += 0.1;
        if (nickname != null && !nickname.trim().isEmpty()) completion += 0.1;
        if (avatarUrl != null && !avatarUrl.trim().isEmpty()) completion += 0.1;

        // 验证状态 (30%)
        if (Boolean.TRUE.equals(emailVerified)) completion += 0.15;
        if (Boolean.TRUE.equals(phoneVerified)) completion += 0.15;

        // 详细信息 (30%)
        if (phone != null && !phone.trim().isEmpty()) completion += 0.15;
        if (preferences != null && !preferences.isEmpty()) completion += 0.15;

        this.profileCompletion = BigDecimal.valueOf(completion).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 增加脚本生成次数
     */
    public void incrementScriptGeneration() {
        this.scriptGenerationCount = (this.scriptGenerationCount == null ? 0 : this.scriptGenerationCount) + 1;
        this.lastActiveTime = LocalDateTime.now();
    }

    /**
     * 增加模板创建次数
     */
    public void incrementTemplateCreation() {
        this.templateCreationCount = (this.templateCreationCount == null ? 0 : this.templateCreationCount) + 1;
        this.lastActiveTime = LocalDateTime.now();
    }

    /**
     * 更新最后活跃时间
     */
    public void updateLastActiveTime() {
        this.lastActiveTime = LocalDateTime.now();
    }

    /**
     * 增加登录次数
     */
    public void incrementLoginCount() {
        this.loginCount = (this.loginCount == null ? 0 : this.loginCount) + 1;
        this.lastLoginTime = LocalDateTime.now();
    }

    /**
     * 检查用户是否激活
     */
    public boolean isActive() {
        return status != null && status == 1;
    }

    /**
     * 检查用户是否是管理员
     */
    public boolean isAdmin() {
        return role != null && (role == UserRole.ADMIN || role == UserRole.SUPER_ADMIN);
    }

    /**
     * 用户角色枚举
     */
    public enum UserRole {
        USER("普通用户"),
        ADMIN("管理员"),
        SUPER_ADMIN("超级管理员");

        private final String description;

        UserRole(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    /**
     * 用户状态枚举
     */
    public enum UserStatus {
        ACTIVE(1, "正常"),
        DISABLED(0, "禁用");

        private final int code;
        private final String description;

        UserStatus(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() {
            return code;
        }

        public String getDescription() {
            return description;
        }

        public static UserStatus fromCode(int code) {
            for (UserStatus status : values()) {
                if (status.code == code) {
                    return status;
                }
            }
            throw new IllegalArgumentException("Unknown user status code: " + code);
        }
    }
}
